package GUI;

import java.lang.reflect.InvocationTargetException;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.font.effects.ColorEffect;
import org.newdawn.slick.geom.Vector2f;

import Game.GameHelper;
import Game.Items.GameItem;
import Game.Items.Inventory;
import Game.Objects.GOPlayer;
import Screens.Manager.Screen;
import Tools.SoundManager;

/** GUI Inventory class
 * @author Aikidos
 */
public class GuiInventory {

	/** Player */
	private GOPlayer _player;

	/** Game screen */
	private Screen _gameScreen;

	/** Normal font */
	private UnicodeFont _fontNormal;
	
	/** Selected font */
	private UnicodeFont _fontSelected;
	
	/** Weight normal font */
	private UnicodeFont _fontWeightNormal;
	
	/** Weight overload font */
	private UnicodeFont _fontWeightOverload;

	/** Icon of equip weapon */
	private Image _iconEquipWeapon;
	
	/** Icon of equip helmet */
	private Image _iconEquipHelmet;
	
	/** Icon of equip chestplate */
	private Image _iconEquipChestplate;
	
	/** Icon of equip shield */
	private Image _iconEquipShield;
	
	/** Icon of equip gloves */
	private Image _iconEquipGloves;
	
	/** Icon of equip boots */
	private Image _iconEquipBoots;
	
	/** Image of help info */
	private Image _helpInfo;

	/** Inventory is open? */
	private boolean _isOpen;

	/** Selected index */
	private int _selected = 0;

	public GuiInventory(Screen gameScreen, GOPlayer player)
			throws SlickException {
		this._player = player;
		_gameScreen = gameScreen;

		// Initialize fonts
		_fontNormal = new UnicodeFont("res/fonts/mainfont.ttf", 11, false,
				false);
		_fontNormal.addAsciiGlyphs();
		_fontNormal.getEffects().add(new ColorEffect(java.awt.Color.GRAY));
		_fontNormal.loadGlyphs();

		_fontSelected = new UnicodeFont("res/fonts/mainfont.ttf", 11, false,
				false);
		_fontSelected.addAsciiGlyphs();
		_fontSelected.getEffects().add(new ColorEffect(java.awt.Color.WHITE));
		_fontSelected.loadGlyphs();
		
		_fontWeightNormal = new UnicodeFont("res/fonts/mainfont.ttf", 8, false,
				false);
		_fontWeightNormal.addAsciiGlyphs();
		_fontWeightNormal.getEffects().add(new ColorEffect(java.awt.Color.YELLOW));
		_fontWeightNormal.loadGlyphs();
		
		_fontWeightOverload = new UnicodeFont("res/fonts/mainfont.ttf", 8, false,
				false);
		_fontWeightOverload.addAsciiGlyphs();
		_fontWeightOverload.getEffects().add(new ColorEffect(java.awt.Color.RED));
		_fontWeightOverload.loadGlyphs();

		// Load sprites
		_iconEquipWeapon = new Image("res/gfx/icons/equip_weapon.png");
		_iconEquipHelmet = new Image("res/gfx/icons/equip_helmet.png");
		_iconEquipChestplate = new Image("res/gfx/icons/equip_chestplate.png");
		_iconEquipShield = new Image("res/gfx/icons/equip_shield.png");
		_iconEquipGloves = new Image("res/gfx/icons/equip_gloves.png");
		_iconEquipBoots = new Image("res/gfx/icons/equip_boots.png");
		_helpInfo = new Image("res/gfx/inventory_help.png");
	}

	/** Returns true if inventory is opened
	 * @return True if inventory is opened
	 */
	public boolean isOpen() {
		return _isOpen;
	}

	/** Update GUI 
	 * @param delta - Time delta
	 */
	public void update(int delta) throws SlickException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
		if (_selected > (_player.getInventory().getItems().size() - 1))
			_selected = 0;
		if (_selected < 0) _selected = _player.getInventory().getItems().size() - 1;
		
		if (_isOpen) {
			// Get input system
			Input input = GameHelper.getGame().getInput();

			// Select item
			if (input.isKeyPressed(Input.KEY_UP)) {
				_selected--;
			}
			if (input.isKeyPressed(Input.KEY_DOWN)) {
				_selected++;
			}

			// On/Off/Use selected item
			if (input.isKeyPressed(Input.KEY_RETURN)) {
				if (!_player.getInventory().isEmpty()) {
					int oldSelected = _selected;
					
					Inventory playerInventory = _player.getInventory();
					GameItem gameItem = playerInventory.getItems().get(
							_selected);
					playerInventory.useItem(gameItem);

					// Play sound
					if (gameItem.isOn())
						SoundManager.play("sfx_equip");
					
					if (oldSelected == playerInventory.getItems().size())
						_selected--;
				}
			}

			// Delete item
			if (input.isKeyPressed(Input.KEY_DELETE)) {
				if (_isOpen) {
					int oldSelected = _selected;
					
					Inventory playerInventory = _player.getInventory();
					GameItem gameItem = playerInventory.getItems().get(
							_selected);
					if (gameItem.isCanBeDeleted()) {
						if (gameItem.isOn())
							gameItem.off();
						playerInventory.deleteItem(gameItem, true);

						// Show message
						GuiManager.getMessenger()
								.addMessage("[green]You[/green] dropped a [yellow]"
										+ gameItem.getName() + "[/yellow]");
					}
					
					if (oldSelected == playerInventory.getItems().size())
						_selected--;
				}
			}
		}
	}

	/** Draw GUI 
	 * @param g - Slick2d graphics
	 */
	public void draw(Graphics g) throws SlickException {
		if (_isOpen) {
			g.setColor(Color.black);
			g.fillRect(0, 0, 350, GameHelper.getGame().getHeight());
			g.fillRect(0, 0, GameHelper.getGame().getWidth(), 300);
			g.setColor(Color.darkGray);
			g.fillRect(0, 
					GameHelper.getGame().getHeight() / 2 - 35, 
					350, 30);

			// Draw items names
			{
				int index = 0;
				float drawY = (GameHelper.getGame().getHeight() / 2) - (_selected + 1) * 30;
				UnicodeFont drawFont = _fontNormal;
				for (GameItem gameItem : _player.getInventory().getItems()) {

					// Draw equip icons
					if (gameItem.isOn()) {
						switch (gameItem.Category) {
						case Weapon:
							_iconEquipWeapon.draw(13, drawY + 1);
							break;
						case Helmet:
							_iconEquipHelmet.draw(13, drawY + 1);
							break;
						
						case Chestplate:
							_iconEquipChestplate.draw(13, drawY + 1);
							break;
						
						case Shield:
							_iconEquipShield.draw(13, drawY + 1);
							break;
						
						case Gloves:
							_iconEquipGloves.draw(13, drawY + 1);
							break;
							
						case Boots:
							_iconEquipBoots.draw(13, drawY + 1);
							break;
						}
					}

					// If item is selected set draw font
					if (_selected == index) {
						drawFont = _fontSelected;
					
						// Draw item info
						gameItem.drawInfo(new Vector2f(370, 10), g);
						
						// Draw item weight
						_fontWeightNormal.drawString(360, 280, "Weight: " + gameItem.getWeight() +"kg");
					
					} else
						drawFont = _fontNormal;

					String itemName = gameItem.getName();
					if (gameItem.isStackable() && (gameItem.getNumOfItems() > 1))
						itemName += " [x" + gameItem.getNumOfItems() + "]";
					
					drawFont.drawString(40, drawY, itemName);

					drawY += 30;
					index++;
				}
			}
			
			// Draw weight
			{
				g.setColor(Color.black);
				g.fillRect(0, GameHelper.getGame().getHeight() - 40, 350, GameHelper.getGame().getHeight());
				
				String currentWeight = String.valueOf(_player.getWeight());
				if ((currentWeight.indexOf(".") + 3) < currentWeight.length())
					currentWeight = currentWeight.substring(0, currentWeight.indexOf(".") + 3);
				
				UnicodeFont drawFont = _player.isOverload() ? _fontWeightOverload : _fontWeightNormal;
				drawFont.drawString(20, GameHelper.getGame().getHeight() - 25, 
						"Weight: " + currentWeight + "/" + _player.MaxWeight + "kg");
			}

			// Draw help info image
			_helpInfo
					.draw((GameHelper.getGame().getWidth() - _helpInfo
							.getWidth()) - 30, (GameHelper.getGame()
							.getHeight() - _helpInfo.getHeight()) - 30);
		}
	}

	/** Open inventory */
	public void open() {
		_isOpen = true;

		// Lock camera control
		_player.getObjectManager().getCamera().lock();
	}

	/** Close inventory */
	public void close() {
		_isOpen = false;

		// Unlock camera control
		_player.getObjectManager().getCamera().unlock();
	}
}
